/**
 * 虚拟化渲染 Hook - 核心实现
 *
 * ========== 虚拟化渲染原理详解 ==========
 *
 * 🎯 核心目标：只渲染用户当前可见区域内的节点，大幅提升大规模数据渲染性能
 *
 * 📊 性能对比：
 * - 传统方案：1000个节点 = 1000个DOM元素，内存占用高，渲染慢，交互卡顿
 * - 虚拟化方案：1000个节点 = ~20个DOM元素，内存占用低，渲染快，交互流畅
 *
 * 🔧 算法流程：
 * 1. 坐标转换：将屏幕视口坐标转换为画布坐标系
 * 2. 碰撞检测：使用矩形相交算法找出与视口重叠的节点
 * 3. 缓冲机制：预渲染视口周围的节点，避免滚动时出现空白
 * 4. 性能监控：实时统计渲染效率和计算耗时
 * 5. 动态更新：当用户缩放或平移时，重新计算可见节点列表
 */

import { useState, useEffect, type RefObject } from 'react';
import type { OKRNode } from '../../../types/okr';
import type { TreeLayout } from '../components/OKRTreeView';
import { performanceMonitor } from '../utils/PerformanceMonitor';

/**
 * 虚拟化渲染统计信息接口
 */
interface VirtualizationStats {
  /** 总节点数量 */
  totalNodes: number;
  /** 当前可见节点数量 */
  visibleNodes: number;
  /** 虚拟化计算耗时（毫秒） */
  renderTime: number;
  /** 渲染效率百分比 */
  efficiency: string;
  /** 性能提升倍数 */
  performanceGain: string;
  /** 内存节省百分比 */
  memorySaved: string;
}

/**
 * 虚拟化渲染 Hook
 *
 * @param nodes 所有节点数据映射表
 * @param layout 布局信息（节点位置、连接线）
 * @param containerRef 容器DOM引用，用于获取视口尺寸
 * @param scale 当前缩放比例（1.0 = 100%）
 * @param translate 当前平移偏移量（像素）
 * @returns 可见节点列表和性能统计信息
 */
export const useVirtualizedRendering = (
  nodes: Record<string, OKRNode>,
  layout: TreeLayout,
  containerRef: RefObject<HTMLDivElement>,
  scale: number,
  translate: { x: number; y: number }
) => {
  // ========== 状态管理 ==========

  /** 存储当前可见的节点ID列表 */
  const [visibleNodes, setVisibleNodes] = useState<string[]>([]);

  /** 性能统计信息，用于监控虚拟化效果 */
  const [renderStats, setRenderStats] = useState<VirtualizationStats>({
    totalNodes: 0,
    visibleNodes: 0,
    renderTime: 0,
    efficiency: '0%',
    performanceGain: '0x',
    memorySaved: '0%'
  });

  // ========== 核心虚拟化算法 ==========

  useEffect(() => {
    // 🕐 开始性能计时
    const startTime = performance.now();

    // 安全检查：确保容器DOM存在
    if (!containerRef.current) {
      console.warn('⚠️ 虚拟化渲染：容器DOM引用不存在');
      return;
    }

    const container = containerRef.current;
    // 获取容器在屏幕上的位置和尺寸信息
    const containerRect = container.getBoundingClientRect();

    // ========== 第一步：坐标系转换 ==========
    // 将屏幕坐标系转换为画布坐标系
    //
    // 🧮 坐标转换公式：画布坐标 = (屏幕坐标 - 平移量) / 缩放比例
    //
    // 📝 举例说明：
    // - 用户将画布向右拖动100px：translate.x = 100
    // - 用户放大到200%：scale = 2.0
    // - 屏幕左边界对应的画布坐标：(-100) / 2.0 = -50
    //
    // 🎯 目的：将用户看到的屏幕区域映射到画布上的实际区域

    const viewportLeft = -translate.x / scale; // 视口左边界在画布中的X坐标
    const viewportTop = -translate.y / scale; // 视口上边界在画布中的Y坐标
    const viewportRight = viewportLeft + containerRect.width / scale; // 视口右边界
    const viewportBottom = viewportTop + containerRect.height / scale; // 视口下边界

    // ========== 第二步：缓冲区计算 ==========
    // 在视口周围添加缓冲区，提前渲染即将进入视野的节点
    //
    // 💡 为什么需要缓冲区？
    // 1. 避免用户快速滚动时出现"节点闪现"的问题
    // 2. 提前准备即将进入视野的节点，提升用户体验
    // 3. 平衡性能和体验：缓冲区太小会闪烁，太大会影响性能

    const buffer = 200; // 缓冲区大小：200像素（约1个节点的高度）

    // 扩展视口范围，包含缓冲区
    const bufferedLeft = viewportLeft - buffer; // 扩展后的左边界
    const bufferedTop = viewportTop - buffer; // 扩展后的上边界
    const bufferedRight = viewportRight + buffer; // 扩展后的右边界
    const bufferedBottom = viewportBottom + buffer; // 扩展后的下边界

    // ========== 第三步：碰撞检测算法 ==========
    // 使用矩形相交算法找出与扩展视口重叠的节点
    //
    // 🔍 矩形相交判断条件：
    // 两个矩形相交 ⟺ 在X轴和Y轴上都有重叠
    // - X轴重叠：rect1.left <= rect2.right && rect1.right >= rect2.left
    // - Y轴重叠：rect1.top <= rect2.bottom && rect1.bottom >= rect2.top
    //
    // ⚡ 算法优势：
    // - 时间复杂度：O(n) - 只需遍历一次所有节点
    // - 空间复杂度：O(1) - 只使用常数级额外空间
    // - 精确性：完全准确的碰撞检测，不会遗漏或多渲染节点

    const visible = Object.entries(layout.positions)
      .filter(([nodeId, position]) => {
        // 计算节点的边界坐标
        const nodeLeft = (position as any).x; // 节点左边界
        const nodeTop = (position as any).y; // 节点上边界
        const nodeRight = (position as any).x + (position as any).width; // 节点右边界
        const nodeBottom = (position as any).y + (position as any).height; // 节点下边界

        // 🔍 X轴重叠检测
        // 节点左边界 <= 视口右边界 && 节点右边界 >= 视口左边界
        const xOverlap = nodeLeft <= bufferedRight && nodeRight >= bufferedLeft;

        // 🔍 Y轴重叠检测
        // 节点上边界 <= 视口下边界 && 节点下边界 >= 视口上边界
        const yOverlap = nodeTop <= bufferedBottom && nodeBottom >= bufferedTop;

        // ✅ 只有在X轴和Y轴都有重叠时，节点才被认为是可见的
        const isVisible = xOverlap && yOverlap;

        // 🐛 开发环境调试信息（仅在详细调试模式下启用）
        if (import.meta.env.DEV && import.meta.env.VITE_DEBUG_VIRTUALIZATION === 'true') {
          if (isVisible) {
            console.log(`👁️ 可见节点: ${nodeId}`, {
              节点位置: `(${nodeLeft}, ${nodeTop}) - (${nodeRight}, ${nodeBottom})`,
              视口位置: `(${bufferedLeft}, ${bufferedTop}) - (${bufferedRight}, ${bufferedBottom})`,
              X轴重叠: xOverlap,
              Y轴重叠: yOverlap
            });
          }
        }

        return isVisible;
      })
      // 提取节点ID，丢弃位置信息
      .map(([nodeId]) => nodeId);

    // ========== 第四步：状态更新 ==========
    // 更新可见节点列表，触发React重新渲染
    setVisibleNodes(visible);

    // ========== 第五步：性能统计和监控 ==========
    // 计算虚拟化渲染的性能指标，用于监控和优化

    const endTime = performance.now();
    const totalNodeCount = Object.keys(nodes).length;
    const visibleNodeCount = visible.length;
    const computeTime = endTime - startTime;

    // 计算性能指标
    const efficiency = totalNodeCount > 0 ? ((visibleNodeCount / totalNodeCount) * 100).toFixed(1) : '0';
    const performanceGain = totalNodeCount > 0 ? (totalNodeCount / Math.max(visibleNodeCount, 1)).toFixed(1) : '1';
    const memorySaved = totalNodeCount > 0 ? ((1 - visibleNodeCount / totalNodeCount) * 100).toFixed(1) : '0';

    // 更新性能统计状态
    const newStats: VirtualizationStats = {
      totalNodes: totalNodeCount,
      visibleNodes: visibleNodeCount,
      renderTime: computeTime,
      efficiency: `${efficiency}%`,
      performanceGain: `${performanceGain}x`,
      memorySaved: `${memorySaved}%`
    };

    setRenderStats(newStats);

    // ========== 集成性能监控系统 ==========
    // 将虚拟化渲染的性能数据记录到性能监控器中
    // 用于长期性能追踪、趋势分析和自动优化建议
    performanceMonitor.recordRenderPerformance(
      computeTime,        // 渲染耗时
      totalNodeCount,     // 总节点数量
      visibleNodeCount    // 可见节点数量
    );

    // ========== 开发环境性能监控和调试 ==========
    // 在开发环境下输出详细的性能信息，帮助开发者优化
    if (import.meta.env.DEV) {
      // 🚀 基础性能统计
      console.log(`🚀 虚拟化渲染统计:`, {
        "📊 总节点数": totalNodeCount,
        "👁️ 可见节点数": visibleNodeCount,
        "⚡ 渲染效率": `${efficiency}% (渲染${visibleNodeCount}个，跳过${totalNodeCount - visibleNodeCount}个)`,
        "⏱️ 计算耗时": `${computeTime.toFixed(2)}ms`,
        "🎯 性能提升": `${performanceGain}x (减少${totalNodeCount - visibleNodeCount}个DOM节点)`,
        "💾 内存节省": `${memorySaved}%`
      });

      // ⚠️ 性能警告和优化建议
      if (visibleNodeCount > 100) {
        console.warn("⚠️ 可见节点数量较多 (>100)，建议优化：", {
          建议1: "增加缓冲区大小，减少频繁重新渲染",
          建议2: "检查节点布局是否过于密集",
          建议3: "考虑实现分层渲染（LOD）"
        });
      }

      if (computeTime > 16) {
        // 16ms ≈ 60FPS，超过这个时间可能影响流畅度
        console.warn("⚠️ 虚拟化计算耗时过长，可能影响滚动流畅度：", {
          当前耗时: `${computeTime.toFixed(2)}ms`,
          目标耗时: "< 16ms (60FPS)",
          优化建议: [
            "考虑使用四叉树空间索引",
            "减少节点数据的复杂度",
            "使用Web Worker进行计算"
          ]
        });
      }

      // 📈 性能等级评估
      const performanceLevel = computeTime < 1 ? "🚀 极快" :
        computeTime < 5 ? "⚡ 快速" :
          computeTime < 16 ? "✅ 良好" : "⚠️ 需优化";

      console.log(`📈 性能等级: ${performanceLevel}`);

      // 🎮 详细调试信息（仅在详细调试模式下显示）
      if (import.meta.env.VITE_DEBUG_VIRTUALIZATION === 'true') {
        console.log(`🎮 详细调试信息:`, {
          "🖼️ 视口信息": {
            原始视口: `(${viewportLeft.toFixed(1)}, ${viewportTop.toFixed(1)}) - (${viewportRight.toFixed(1)}, ${viewportBottom.toFixed(1)})`,
            缓冲视口: `(${bufferedLeft.toFixed(1)}, ${bufferedTop.toFixed(1)}) - (${bufferedRight.toFixed(1)}, ${bufferedBottom.toFixed(1)})`,
            缓冲区大小: `${buffer}px`
          },
          "🔧 变换参数": {
            缩放比例: `${scale}x (${(scale * 100).toFixed(0)}%)`,
            平移偏移: `(${translate.x}px, ${translate.y}px)`
          },
          "📏 容器尺寸": {
            宽度: `${containerRect.width}px`,
            高度: `${containerRect.height}px`
          }
        });
      }
    }

    // 🔄 清理函数：在组件卸载时执行清理工作
    return () => {
      // 虚拟化渲染通常不需要特殊清理，但可以在这里添加必要的清理逻辑
      if (import.meta.env.DEV && import.meta.env.VITE_DEBUG_VIRTUALIZATION === 'true') {
        console.log('🧹 虚拟化渲染清理完成');
      }
    };

  }, [layout, scale, translate, containerRef, nodes]); // 依赖项：当这些值变化时重新计算

  // ========== 返回结果 ==========
  return {
    /** 当前可见的节点ID列表 */
    visibleNodes,
    /** 性能统计信息 */
    renderStats
  };
};

/**
 * 导出类型定义，供其他组件使用
 */
export type { VirtualizationStats };
